#include "ADUGameManager.h"
#include "ADUConfig.h"
#include "GB2ShapeCache-x.h"
#include "ADUIntroScene.h"
#include "cocos2d.h"
USING_NS_CC;

class SplashLayer;

GameManager *GameManager::m_instance = NULL;

GameManager::GameManager() {
	b2Vec2 _gravity;
	_gravity.Set(0.0f, -10.0f);
	mWorld = new b2World(_gravity);
	// mWorld->SetAllowSleeping(true);
	// mWorld->SetContinuousPhysics(true);
#ifndef IGNORE_FILTER
	mWorld->SetContactFilter(&mContactFilter);
#endif
	prevBasinID = 1;
	gameScore = prevBasinID;
    gameLevel = 1;
	ptmRatio = 32;
	// load physics shapes
    GB2ShapeCache::sharedGB2ShapeCache()->addShapesWithFile("body.plist");
    
    for(int i =0; i < MAX_PARTICLE; i++){
        collisionCache[i] = false;
    }

}

void GameManager::SetColisionCache(int index, bool collisioned){
    collisionCache[index] = collisioned;
}
bool GameManager::GetColisionCache(int index){
    return collisionCache[index];
}


void GameManager::ResetWorld(){
	if (mWorld)
	delete mWorld;
	b2Vec2 _gravity;
	_gravity.Set(0.0f, -10.0f);
	mWorld = new b2World(_gravity);
	// mWorld->SetAllowSleeping(true);
	// mWorld->SetContinuousPhysics(true);
#ifndef IGNORE_FILTER
	mWorld->SetContactFilter(&mContactFilter);
#endif

}

GameManager* GameManager::getInstance() {
	if(m_instance == NULL) {
		m_instance = new GameManager();
	}
	return m_instance;
}

void GameManager::Step(float _time) {
	int _velocityIterations = 8;
    int _positionIterations = 1;    
    mWorld->Step(_time, _velocityIterations, _positionIterations);


    for (b2Body* b = mWorld->GetBodyList();b;b=b->GetNext()){
    	if (b->GetUserData() != NULL){
    		Sprite* sprt = (Sprite*)b->GetUserData();
            
            if (sprt->getTag() == TAG_PIPEHEAD){
                Vec2 pos = sprt->getPosition();
                float baseOffet, offsetX, offsetY;
                baseOffet = 0.5*sprt->getContentSize().width;
                
                float angle = sprt->getRotation();
                angle = angle*PI/180;
                
                offsetX = baseOffet*cos(angle);
                offsetY = baseOffet*sin(angle);
                
                b->SetTransform((pos.x+offsetX-mOffSet.x)/PTM_RATIO, (pos.y-offsetY-mOffSet.y)/PTM_RATIO, (-1)*angle);
                
                return;
            }
            
            
    		Vec2 pos = ccp(ptmRatio * b->GetPositionX(),ptmRatio * b->GetPositionY());
			float rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
			if(sprt) {
				sprt->setPosition(pos);
				sprt->setRotation(rotation);
			}
    	}
    }
}
void GameManager::RunScene(int scene) {
	Scene *pScene = NULL;

    switch(scene)
    {
    	case SPLASH_SCENE:
			pScene = SplashLayer::createScene();
			break;
        case GAMEPLAY_SCENE:
            pScene = GamePlayLayer::createScene();
            break;
        case GAMEOVER_SCENE:
        	pScene = GameOverLayer::createScene();
        	break;
        case INTRO_SCENE:
        	pScene = IntroLayer::createScene();
        	break;
        default:
            log("Unknown scene");
            break;
    }

	if (Director::getInstance()->getRunningScene() == NULL) {
		Director::getInstance()->runWithScene(pScene);
	} else {
		// Director::getInstance()->replaceScene(TransitionSlideInT::create(1, pScene));
		Director::getInstance()->replaceScene(pScene);
	}
}

Sprite* GameManager::GetSprite(const char *file_name) {
	Sprite* pSprite = NULL;
	// Search in the cache firt
	pSprite = Sprite::createWithSpriteFrameName(file_name);
	if(pSprite == NULL) {
		// this is equivalent to the previous example,
		// but it is created by retrieving the spriteframe from the cache.
		auto newspriteFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName(file_name);
		pSprite = Sprite::createWithSpriteFrame(newspriteFrame);
	}
	printf("success %s\n",file_name);
	return pSprite;
}

void GameManager::destroyAllBody() {
	for (b2Body* b = mWorld->GetBodyList();b;b=b->GetNext()){
    	mWorld->DestroyBody(b);
    }
}

float GameManager::getWaterHeight(){
    return mWaterHeight;
}

void GameManager::setWaterHeight(float height){
    mWaterHeight = height;

}


